package cn.bugstack.springframework.beans.factory.annotation;

import cn.bugstack.springframework.aop.InstantiationAwareBeanPostProcessor;
import cn.bugstack.springframework.beans.BeansException;
import cn.bugstack.springframework.beans.PropertyValues;
import cn.bugstack.springframework.beans.factory.BeanFactory;
import cn.bugstack.springframework.beans.factory.ConfigurableListableBeanFactory;
import cn.bugstack.springframework.util.Autowired;
import cn.bugstack.springframework.util.ClassUtils;
import cn.bugstack.springframework.util.Qualifier;
import cn.bugstack.springframework.util.Value;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ClassUtil;

import java.lang.reflect.Field;

public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactory {
    private ConfigurableListableBeanFactory beanFactory;

    public void setBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) {
        // 处理注解@Value
        Class<?> clazz = beanName.getClass();
        clazz = ClassUtils.isCglibProxyClass(clazz) ?clazz.getSuperclass():clazz;

        Field[] decl = clazz.getDeclaredFields();

        for(Field field:decl){
            Value value = field.getAnnotation(Value.class);
            if(null != value){
                String val = value.value();
                val = beanFactory.resolveEmbeddedValue(value);
                BeanUtil.setFieldValue(bean,field.getName(),value);
            }
        }

        // 处理注解@Autowired
        for(Field field:decl){
            Autowired autowired = field.getAnnotation(Autowired.class);
            if(null != autowired){
                Class<?> fileType = field.getType();
                String dependentBeanName = null;
                Qualifier qualifier = field.getAnnotation(Qualifier.class);
                Object o = null;
                if(null != qualifier){
                    dependentBeanName = qualifier.value();
                    o = beanFactory.getBean(dependentBeanName,fileType);
                }else {
                    o = beanFactory.getBean(String.valueOf(fileType));
                }
                BeanUtil.setFieldValue(bean,field.getName(),dependentBeanName);
            }
        }
        return null;
    }

    @Override
    public Object getEarlyBeanReference(Object o, String beanName) {
        return null;
    }

    @Override
    public Object postProcessBeforeInitialization(Class<?> bean, String beanName) throws BeansException {
        return null;
    }

    @Override
    public Object getBean(String name) throws BeansException {
        return null;
    }

    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        return null;
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        return null;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }
}
